import 'package:flutter/material.dart';
import '../animations/animation_config.dart';

/// 加载状态枚举
enum LoadingState {
  loading,
  success,
  error,
  idle,
}

/// 加载指示器类型
enum LoadingIndicatorType {
  circular,
  linear,
  dots,
  pulse,
  spin,
}

/// 加载状态组件
/// 提供局部化的加载反馈，避免全局性阻断
class LoadingWidget extends StatefulWidget {
  const LoadingWidget({
    super.key,
    this.state = LoadingState.loading,
    this.type = LoadingIndicatorType.circular,
    this.size = 24,
    this.color,
    this.strokeWidth = 2,
    this.message,
    this.showMessage = true,
    this.backgroundColor,
    this.backgroundOpacity = 0.1,
    this.child,
  });

  /// 加载状态
  final LoadingState state;
  
  /// 指示器类型
  final LoadingIndicatorType type;
  
  /// 大小
  final double size;
  
  /// 颜色
  final Color? color;
  
  /// 线条宽度
  final double strokeWidth;
  
  /// 加载消息
  final String? message;
  
  /// 是否显示消息
  final bool showMessage;
  
  /// 背景色
  final Color? backgroundColor;
  
  /// 背景透明度
  final double backgroundOpacity;
  
  /// 自定义内容
  final Widget? child;

  @override
  State<LoadingWidget> createState() => _LoadingWidgetState();
}

class _LoadingWidgetState extends State<LoadingWidget>
    with TickerProviderStateMixin {
  late AnimationController _controller;
  late AnimationController _fadeController;
  late Animation<double> _fadeAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationConfig.createController(
      vsync: this,
      duration: const Duration(seconds: 1),
    );
    _fadeController = AnimationConfig.createController(
      vsync: this,
      duration: AnimationConfig.fadeIn,
    );
    _fadeAnimation = AnimationConfig.createFadeAnimation(_fadeController);
    
    _startAnimation();
  }

  @override
  void didUpdateWidget(LoadingWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.state != oldWidget.state) {
      _updateAnimation();
    }
  }

  void _startAnimation() {
    if (widget.state == LoadingState.loading) {
      if (widget.type == LoadingIndicatorType.dots ||
          widget.type == LoadingIndicatorType.pulse) {
        _controller.repeat(reverse: true);
      } else {
        _controller.repeat();
      }
    }
    _fadeController.forward();
  }

  void _updateAnimation() {
    if (widget.state == LoadingState.loading) {
      _startAnimation();
    } else {
      _controller.stop();
      if (widget.state == LoadingState.success ||
          widget.state == LoadingState.error) {
        Future.delayed(const Duration(milliseconds: 500), () {
          if (mounted) {
            _fadeController.reverse();
          }
        });
      }
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    _fadeController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (widget.state == LoadingState.idle) {
      return widget.child ?? const SizedBox.shrink();
    }

    return FadeTransition(
      opacity: _fadeAnimation,
      child: Container(
        padding: const EdgeInsets.all(8),
        decoration: widget.backgroundColor != null
            ? BoxDecoration(
                color: widget.backgroundColor!.withOpacity(widget.backgroundOpacity),
                borderRadius: BorderRadius.circular(8),
              )
            : null,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            _buildIndicator(),
            if (widget.showMessage && widget.message != null) ...[
              const SizedBox(height: 8),
              Text(
                widget.message!,
                style: Theme.of(context).textTheme.bodySmall?.copyWith(
                  color: widget.color ?? Theme.of(context).colorScheme.onSurface,
                ),
              ),
            ],
          ],
        ),
      ),
    );
  }

  Widget _buildIndicator() {
    final color = widget.color ?? Theme.of(context).colorScheme.primary;

    switch (widget.state) {
      case LoadingState.loading:
        return _buildLoadingIndicator(color);
      case LoadingState.success:
        return _buildSuccessIndicator(color);
      case LoadingState.error:
        return _buildErrorIndicator(color);
      case LoadingState.idle:
        return const SizedBox.shrink();
    }
  }

  Widget _buildLoadingIndicator(Color color) {
    switch (widget.type) {
      case LoadingIndicatorType.circular:
        return SizedBox(
          width: widget.size,
          height: widget.size,
          child: CircularProgressIndicator(
            strokeWidth: widget.strokeWidth,
            valueColor: AlwaysStoppedAnimation(color),
          ),
        );
      
      case LoadingIndicatorType.linear:
        return SizedBox(
          width: widget.size,
          height: 4,
          child: LinearProgressIndicator(
            valueColor: AlwaysStoppedAnimation(color),
            backgroundColor: color.withOpacity(0.2),
          ),
        );
      
      case LoadingIndicatorType.dots:
        return _buildDotsIndicator(color);
      
      case LoadingIndicatorType.pulse:
        return _buildPulseIndicator(color);
      
      case LoadingIndicatorType.spin:
        return _buildSpinIndicator(color);
    }
  }

  Widget _buildDotsIndicator(Color color) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Row(
          mainAxisSize: MainAxisSize.min,
          children: List.generate(3, (index) {
            final delay = index * 0.2;
            final value = (_controller.value - delay).clamp(0.0, 1.0);
            final scale = (Curves.easeInOut.transform(value) * 0.5 + 0.5);
            
            return Padding(
              padding: const EdgeInsets.symmetric(horizontal: 2),
              child: Transform.scale(
                scale: scale,
                child: Container(
                  width: widget.size / 4,
                  height: widget.size / 4,
                  decoration: BoxDecoration(
                    color: color,
                    shape: BoxShape.circle,
                  ),
                ),
              ),
            );
          }),
        );
      },
    );
  }

  Widget _buildPulseIndicator(Color color) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        final scale = 0.7 + (Curves.easeInOut.transform(_controller.value) * 0.3);
        final opacity = 1.0 - Curves.easeInOut.transform(_controller.value) * 0.5;
        
        return Transform.scale(
          scale: scale,
          child: Opacity(
            opacity: opacity,
            child: Container(
              width: widget.size,
              height: widget.size,
              decoration: BoxDecoration(
                color: color,
                shape: BoxShape.circle,
              ),
            ),
          ),
        );
      },
    );
  }

  Widget _buildSpinIndicator(Color color) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Transform.rotate(
          angle: _controller.value * 2 * 3.14159,
          child: Icon(
            Icons.refresh,
            size: widget.size,
            color: color,
          ),
        );
      },
    );
  }

  Widget _buildSuccessIndicator(Color color) {
    return Icon(
      Icons.check_circle,
      size: widget.size,
      color: Theme.of(context).colorScheme.primary,
    );
  }

  Widget _buildErrorIndicator(Color color) {
    return Icon(
      Icons.error,
      size: widget.size,
      color: Theme.of(context).colorScheme.error,
    );
  }
}

/// 内联加载组件
/// 用于在内容区域显示小型加载指示器
class InlineLoading extends StatelessWidget {
  const InlineLoading({
    super.key,
    this.size = 16,
    this.color,
    this.message,
  });

  final double size;
  final Color? color;
  final String? message;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        SizedBox(
          width: size,
          height: size,
          child: CircularProgressIndicator(
            strokeWidth: 2,
            valueColor: AlwaysStoppedAnimation(
              color ?? Theme.of(context).colorScheme.primary,
            ),
          ),
        ),
        if (message != null) ...[
          const SizedBox(width: 8),
          Text(
            message!,
            style: Theme.of(context).textTheme.bodySmall,
          ),
        ],
      ],
    );
  }
}

/// 覆盖层加载组件
/// 用于在特定区域显示半透明加载遮罩
class OverlayLoading extends StatelessWidget {
  const OverlayLoading({
    super.key,
    required this.isLoading,
    required this.child,
    this.message,
    this.backgroundColor,
    this.opacity = 0.7,
  });

  final bool isLoading;
  final Widget child;
  final String? message;
  final Color? backgroundColor;
  final double opacity;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        child,
        if (isLoading)
          Positioned.fill(
            child: Container(
              color: (backgroundColor ?? Theme.of(context).colorScheme.surface).withOpacity(opacity),
              child: Center(
                child: LoadingWidget(
                  message: message,
                  backgroundColor: Theme.of(context).colorScheme.surface,
                ),
              ),
            ),
          ),
      ],
    );
  }
}

/// 加载状态构建器
/// 根据不同状态自动切换显示内容
class LoadingBuilder extends StatelessWidget {
  const LoadingBuilder({
    super.key,
    required this.state,
    required this.child,
    this.loadingWidget,
    this.errorWidget,
    this.emptyWidget,
  });

  final LoadingState state;
  final Widget child;
  final Widget? loadingWidget;
  final Widget? errorWidget;
  final Widget? emptyWidget;

  @override
  Widget build(BuildContext context) {
    switch (state) {
      case LoadingState.loading:
        return loadingWidget ?? 
               const Center(child: LoadingWidget());
      
      case LoadingState.error:
        return errorWidget ?? 
               const Center(
                 child: LoadingWidget(
                   state: LoadingState.error,
                   message: '加载失败',
                 ),
               );
      
      case LoadingState.success:
      case LoadingState.idle:
        return child;
    }
  }
}